package web

import (
	"encoding/json"
	"regexp"
	"strings"

	"gddgame.cc/galaxy/common"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/server/web"
	"gddgame.cc/galaxy/server/web/middleware"

	"gddgame.cc/galaxy/utils/def"

	"gopkg.in/yaml.v2"
)

type Consume = string
type Produce = string
type Location = string

const (
	FormConsume Consume = "application/x-www-form-urlencoded"
	FileConsume Consume = "multipart/form-data"
	JsonConsume Consume = "application/json"

	JsonProduce  Produce = "application/json"
	ImageProduce Produce = "image/png"
	DownProduce  Produce = "application/octet-stream"
	TextProduce  Produce = "text/plain"

	HeaderLocation Location = "header"
	CookieLocation Location = "cookie"
	QueryLocation  Location = "query"
	PathLocation   Location = "path"
)

type SwaggerContent struct {
	Description string
	Alias       string
	Schema      interface{} // 只能是：SwaggerSchema, map[string]SwaggerSchema，swaggerSchema
	Object      map[string]SwaggerSchema
}
type SwaggerSchema struct {
	Name        string
	Type        Type
	Required    bool
	Description string
	Schema      interface{} // 只能是：SwaggerSchema, map[string]SwaggerSchema，swaggerSchema
	Format      string
	Object      map[string]SwaggerSchema
	Alias       string
}

type Swagger struct {
	Summary     string
	Description string
	Produce     Produce
	Consume     Consume
	Controller  Ctl
	Controllers []Ctl
	Middlewares []Middleware
	Params      []Param
	Response    *SwaggerContent
	Responses   map[int]*SwaggerContent
	Tags        []string
	Security    []string
	Deprecated  bool
	Download    bool
	Image       bool
}
type SwaggerTag struct {
	Name        string `json:"name" yaml:"name"`
	Description string `json:"description" yaml:"description"`
}
type SwaggerContact struct {
	Name  string `json:"name" yaml:"name"`
	Url   string `json:"url" yaml:"url"`
	Email string `json:"email" yaml:"email"`
}
type SwaggerInfo struct {
	Title       string         `json:"title" yaml:"title"`
	Description string         `json:"description" yaml:"description"`
	Version     string         `json:"version" yaml:"version"`
	Contact     SwaggerContact `json:"contact" yaml:"contact"`
}
type SwaggerServerVariables struct {
	Default     string   `json:"default" yaml:"default"`
	Enum        []string `json:"enum" yaml:"enum"`
	Description string   `json:"description" yaml:"description"`
}

type swaggerParam struct {
	Name        string        `json:"name" yaml:"name"`
	In          Location      `json:"in" yaml:"in"`
	Description string        `json:"description" yaml:"description"`
	Required    bool          `json:"required" yaml:"required"`
	Schema      swaggerSchema `json:"schema" yaml:"schema"`
	Deprecated  bool          `json:"deprecated" yaml:"deprecated"`
}
type swaggerServer struct {
	Url         string                            `json:"url" yaml:"url"`
	Description string                            `json:"description" yaml:"description"`
	Variables   map[string]SwaggerServerVariables `json:"variables" yaml:"variables"`
}
type swaggerPath struct {
	Summary     string                   `json:"summary" yaml:"summary"`
	Description string                   `json:"description" yaml:"description"`
	Parameters  []swaggerParam           `json:"parameters" yaml:"parameters"`
	RequestBody swaggerRequestBody       `json:"requestBody" yaml:"requestBody"`
	Responses   map[int]swaggerResponse  `json:"responses" yaml:"responses"`
	Security    []map[string]interface{} `json:"security" yaml:"security"`
	Tags        []string                 `json:"tags" yaml:"tags"`
	Deprecated  bool                     `json:"deprecated" yaml:"deprecated"`
}
type swaggerRequestBody struct {
	Required    bool                      `json:"required" yaml:"required"`
	Description string                    `json:"description" yaml:"description"`
	Content     map[string]swaggerContent `json:"content" yaml:"content"`
}
type swaggerContent struct {
	Schema swaggerSchema `json:"schema" yaml:"schema"`
}
type swaggerResponse struct {
	Description string                    `json:"description" yaml:"description"`
	Content     map[string]swaggerContent `json:"content" yaml:"content"`
}
type swaggerSecurityScheme struct {
	Type string   `json:"type" yaml:"type"`
	Name string   `json:"name" yaml:"name"`
	In   Location `json:"in" yaml:"in"`
}
type swaggerSchema struct {
	Type        Type                      `json:"type" yaml:"type"`
	Required    []string                  `json:"required" yaml:"required"`
	Format      string                    `json:"format" yaml:"format"`
	Items       *swaggerSchema            `json:"items" yaml:"items"`
	Properties  map[string]*swaggerSchema `json:"properties" yaml:"properties"`
	Description string                    `json:"description" yaml:"description"`
	Default     interface{}               `json:"default" yaml:"default"`
	Ref         string                    `json:"$ref" yaml:"$ref"`
}
type swaggerComponent struct {
	SecuritySchemes map[string]*swaggerSecurityScheme `json:"securitySchemes" yaml:"securitySchemes"`
	Schemas         map[string]*swaggerSchema         `json:"schemas" yaml:"schemas"`
}
type swaggerRouterResult struct {
	Openapi    string                            `json:"openapi" yaml:"openapi"`
	Info       SwaggerInfo                       `json:"info" yaml:"info"`
	Servers    []swaggerServer                   `json:"servers" yaml:"servers"`
	Tags       []SwaggerTag                      `json:"tags" yaml:"tags"`
	Paths      map[string]map[string]swaggerPath `json:"paths" yaml:"paths"`
	Components swaggerComponent                  `json:"components" yaml:"components"`
}
type SwaggerRouter struct {
	web.Router
	manager *swaggerManager
	path    string
	inited  bool
}
type swaggerManager struct {
	debug    bool
	config   *SwaggerRouterConfig
	Security *securityManager
	logger   def.Logger
	servers  []swaggerServer

	tags        map[string]SwaggerTag
	responses   map[int]*swaggerResponse
	definitions map[string]*swaggerSchema
	paths       map[string]map[string]swaggerPath

	refDefinitions   map[string]interface{}
	definitionRandom int
}

func (r *SwaggerRouter) init() {
	if r.inited {
		return
	}

	router := r.Router
	manager := r.manager
	path := r.path
	config := manager.config
	if manager.debug || config.Force {
		router.Get("/"+config.Url+".json", func(context web.Context, next web.Next) error {
			return json.NewEncoder(context.Writer()).Encode(manager.getInfo())
		})
		manager.logger.Debugf("Swagger register:%s/%s.json", path, manager.config.Url)
		router.Get("/"+config.Url+".yaml", func(context web.Context, next web.Next) error {
			return yaml.NewEncoder(context.Writer()).Encode(manager.getInfo())
		})
		manager.logger.Debugf("Swagger register:%s/%s.yaml", path, manager.config.Url)
	}
	r.inited = true
}

func (r *SwaggerRouter) Group(pattern string) *SwaggerRouter {
	r.init()
	rr := r.Router.Group(pattern)
	return &SwaggerRouter{Router: rr, manager: r.manager, path: r.path + pattern}
}
func (r *SwaggerRouter) Get(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "get", &config)
	if middles != nil {
		r.Router.Get(pattern, middles...)
	}
}
func (r *SwaggerRouter) Post(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "post", &config)
	if middles != nil {
		r.Router.Post(pattern, middles...)
	}
}
func (r *SwaggerRouter) Put(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "put", &config)
	if middles != nil {
		r.Router.Put(pattern, middles...)
	}
}
func (r *SwaggerRouter) Delete(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "delete", &config)
	if middles != nil {
		r.Router.Delete(pattern, middles...)
	}
}
func (r *SwaggerRouter) Connect(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "connect", &config)
	if middles != nil {
		r.Router.Connect(pattern, middles...)
	}
}
func (r *SwaggerRouter) Options(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "options", &config)
	if middles != nil {
		r.Router.Options(pattern, middles...)
	}
}
func (r *SwaggerRouter) Head(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "head", &config)
	if middles != nil {
		r.Router.Head(pattern, middles...)
	}
}
func (r *SwaggerRouter) Trace(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "trace", &config)
	if middles != nil {
		r.Router.Trace(pattern, middles...)
	}
}
func (r *SwaggerRouter) Patch(pattern string, config Swagger) {
	r.init()
	middles := r.manager.parsePath(pattern, "patch", &config)
	if middles != nil {
		r.Router.Patch(pattern, middles...)
	}
}
func (r *SwaggerRouter) Security() *securityManager {
	return r.manager.Security
}
func (r *SwaggerRouter) RegisterServer(url string, description string, schema map[string]SwaggerServerVariables) {
	r.manager.servers = append(r.manager.servers, swaggerServer{
		Url:         url,
		Description: description,
		Variables:   schema,
	})
}
func (r *SwaggerRouter) RegisterResponse(status int, description string, res *SwaggerContent, alias string) int {
	if alias == "" {
		alias = res.Alias
	}

	r.manager.responses[status] = &swaggerResponse{
		Description: description,
		Content:     r.manager.parseContent(string(r.manager.config.Produce), res, alias),
	}
	return status
}

func (r *SwaggerRouter) RegisterSchema(schema map[string]SwaggerSchema, alias string) *swaggerSchema {
	return r.manager.parseObject(&schema, alias, true)
}
func (r *swaggerManager) parsePath(path string, method string, config *Swagger) []Middleware {
	path = formatPath(path)
	methods, ok := r.paths[path]
	if ok {
		if _, ok := methods[method]; ok {
			r.logger.Error("parse:" + method + ":" + path + " exist!")
			return nil
		}
	} else {
		methods = map[string]swaggerPath{}
	}
	if config.Response == nil && config.Responses == nil {
		r.logger.Error(method + ":" + path + " responses not defined!")
		return nil
	}
	if config.Controller != nil {
		config.Controllers = []Ctl{config.Controller}
	}
	if len(config.Controllers) == 0 {
		r.logger.Error(method + ":" + path + " controller not defined!")
		return nil
	}
	r.logger.Debugf("parse:" + method + ":" + path + "")
	consume := config.Consume
	produce := config.Produce
	body := &SwaggerContent{
		Object: map[string]SwaggerSchema{},
	}
	parameters := []swaggerParam{}

	for _, param := range config.Params {
		key := param.Name
		if param.In == Cache {
			continue
		}
		if param.In == File {
			consume = FileConsume
		} else if param.In == Form && consume != FormConsume && consume != FileConsume {
			consume = FormConsume
		}
		location := Location(param.In)
		if location == PathLocation || location == QueryLocation || location == HeaderLocation || location == CookieLocation {
			parameters = append(parameters, *r.parseParam(key, &param))
		} else if param.In == All {
			if param.Type == "" {
				param.Type = Object
			}
			body.Schema = *r.parseSchema(&param)
		} else {
			body.Object[key] = *r.parseSchema(&param)
		}
	}
	if config.Download || config.Image {
		produce = DownProduce
		if config.Image {
			produce = ImageProduce
		}
		// controller.push(download)
		if config.Middlewares == nil {
			config.Middlewares = []Middleware{middleware.Download}
		} else {
			config.Middlewares = append(config.Middlewares, middleware.Download)
		}
		config.Response = &SwaggerContent{
			Schema: map[string]SwaggerSchema{
				"field": {
					Type: Files,
				},
			},
		}
	}
	setting := swaggerPath{
		Summary:     config.Summary,
		Description: config.Description,
		Parameters:  parameters,
		Responses:   r.parseResponse(produce, config.Response, config.Responses, path),
		Deprecated:  config.Deprecated,
	}
	r.parseBody(&setting, consume, body, path)
	r.parseTags(&setting, config.Tags)
	sm := r.parseSecurity(&setting, config.Security)
	if sm != nil {
		config.Middlewares = append(config.Middlewares, sm)
	}
	methods[method] = setting
	if config.Middlewares == nil || len(config.Middlewares) == 0 {
		return []Middleware{Controller(config.Params, config.Controllers...)}
	} else {
		return append(config.Middlewares, Controller(config.Params, config.Controllers...))
	}
}

func (r *swaggerManager) parseParam(key string, param *Param) *swaggerParam {
	if param.In == Path {
		param.Required = true
	}
	p := &swaggerParam{
		Required:    param.Required,
		Name:        key,
		In:          Location(param.In),
		Description: param.Description,
	}
	if p.Name == "" {
		p.Name = key
	}
	p.Schema = *r.parseField(p.Name, r.parseSchema(param), "")
	return p
}
func (r *swaggerManager) parseSchema(param *Param) *SwaggerSchema {
	return &SwaggerSchema{
		Type:        param.Type,
		Description: param.Description,
	}
}
func (r *swaggerManager) parseField(name string, field *SwaggerSchema, parentAlias string) *swaggerSchema {
	var schema *swaggerSchema

	if field.Schema != nil || field.Object != nil {
		alias := field.Alias
		if alias == "" {
			alias = aliasWithParent(name, parentAlias)
		}
		if field.Object != nil {
			schema = r.parseObject(field.Object, alias, false)
		} else {
			schema = r.parseObject(field.Schema, alias, true)
		}
	}
	if schema == nil {
		schema = &swaggerSchema{}
	}
	if schema.Ref != "" {
		schema.Type = field.Type
		schema.Description = field.Description
	}
	if field.Format != "" {
		schema.Format = field.Format
	}

	if field.Type == Files {
		schema.Format = "binary"
	}
	return schema
}
func (r *swaggerManager) parseContent(mediaType string, content *SwaggerContent, alias string) map[string]swaggerContent {
	var schema *swaggerSchema

	if content.Object != nil {
		schema = r.parseObject(content.Object, alias, false)
	} else {
		schema = r.parseObject(content.Schema, alias, true)
	}
	return map[string]swaggerContent{
		mediaType: {
			Schema: *schema,
		},
	}
}
func (r *swaggerManager) parseObject(object interface{}, alias string, schema bool) *swaggerSchema {
	if s, ok := object.(*swaggerSchema); ok {
		return s
	} else if s, ok := object.(*SwaggerSchema); ok {
		var item *swaggerSchema
		if s.Type != Array && s.Type != Object {
			r.logger.Error("parseObject => SwaggerSchema must Array or Object type")
			return nil
		} else if SS, ok := s.Schema.(*SwaggerSchema); ok {
			item = r.parseField("", SS, alias)
		} else if s.Object != nil {
			item = r.parseObject(s.Object, alias, false)
		} else {
			item = r.parseObject(s.Schema, alias, true)
		}
		ss := &swaggerSchema{
			Type: s.Type,
		}
		if item != nil {
			ss.Items = item
		}
		return ss
	}
	s, ok := object.(map[string]SwaggerSchema)
	if !ok {
		r.logger.Error("parseObject => must *SwaggerSchema, map[string]SwaggerSchema，*swaggerSchema")
		return nil
	}
	if schema {
		for key, _ := range r.refDefinitions {
			if &object != r.refDefinitions[key] {
				continue
			}
			return &swaggerSchema{
				Ref: `#/components/schemas/` + key,
			}
		}
	}

	properties := map[string]*swaggerSchema{}
	required := []string{}
	for key, i := range s {
		item := &i
		properties[key] = r.parseField(key, item, alias)
		if s[key].Required {
			required = append(required, key)
		}
	}

	key := alias
	if key == "" {
		key = `Object` + string(r.definitionRandom)
		r.definitionRandom += 1
	}
	o := &swaggerSchema{
		Type:       Object,
		Properties: properties,
	}
	if len(required) > 0 {
		o.Required = required
	}
	if !schema {
		return o
	}
	r.definitions[key] = o
	r.refDefinitions[key] = &object
	return &swaggerSchema{
		Ref: `#/components/schemas/` + key,
	}
}
func (r *swaggerManager) parseResponse(mediaType Produce, response *SwaggerContent, responses map[int]*SwaggerContent, path string) map[int]swaggerResponse {
	if response != nil {
		if responses == nil {
			responses = make(map[int]*SwaggerContent)
		}
		responses[200] = response
	}
	if len(responses) == 0 {
		r.logger.Error("parseResponse need response " + path)
		return nil
	}

	sr := make(map[int]swaggerResponse)
	for key, value := range r.responses {
		sr[key] = *value
	}
	for key, value := range responses {
		alias := value.Alias
		if alias == "" {
			alias = pathToAlias(path)
		}
		sr[key] = swaggerResponse{
			Description: value.Description,
			Content:     r.parseContent(string(mediaType), value, alias),
		}
	}
	return sr
}
func (r *swaggerManager) parseBody(settings *swaggerPath, mediaType Consume, body *SwaggerContent, path string) {
	alias := body.Alias
	if alias == "" {
		alias = pathToAlias(path)
	}
	settings.RequestBody = swaggerRequestBody{
		Required: true,
		Content:  r.parseContent(string(mediaType), body, alias),
	}
}
func (r *swaggerManager) parseTags(settings *swaggerPath, tags []string) {
	if len(tags) > 0 {
		t := []string{}
		for _, value := range tags {
			if _, ok := r.tags[value]; ok {
				t = append(t, value)
			}
		}
		settings.Tags = t
	}
}
func (r *swaggerManager) parseSecurity(settings *swaggerPath, security []string) web.Handler {
	a := []map[string]interface{}{}
	if security == nil {
		// 没有设置为默认
		for _, value := range r.Security.d {
			c := map[string]interface{}{}
			c[value] = nil
			a = append(a, c)
		}
		settings.Security = a
		return r.Security.middleware(nil)
	}
	if len(security) > 0 {
		s := []string{}
		for _, value := range security {
			if _, ok := r.Security.middlewares[value]; ok {
				s = append(s, value)
				c := map[string]interface{}{}
				c[value] = nil
				a = append(a, c)
			}
		}
		settings.Security = a
		return r.Security.middleware(s)
	} else {
		// 设置为空为不验证
		return nil
	}
}
func (r *swaggerManager) getInfo() *swaggerRouterResult {
	config := r.config
	result := &swaggerRouterResult{}
	result.Info = config.Info
	result.Openapi = "3.0.0"
	result.Tags = config.Tags
	result.Components = swaggerComponent{
		SecuritySchemes: r.Security.schemes(),
		Schemas:         r.definitions,
	}
	result.Paths = r.paths
	result.Servers = r.servers
	return result
}

type securityManager struct {
	fail           func() error
	d              []string
	generateMiddle map[string]web.Handler
	middlewares    map[string]common.AuthHandler
	schemaMap      map[string]*swaggerSecurityScheme
}

func (security *securityManager) init() {
	security.fail = func() error {
		return AuthException("401 Unauthorized")
	}
	security.generateMiddle = make(map[string]web.Handler)
	security.middlewares = make(map[string]common.AuthHandler)
	security.schemaMap = make(map[string]*swaggerSecurityScheme)
}

func (security *securityManager) schemes() map[string]*swaggerSecurityScheme {
	return security.schemaMap
}

func (security *securityManager) middleware(list []string) web.Handler {
	if len(list) == 0 {
		if len(security.d) == 0 {
			return nil
		}
		list = security.d
	}
	key := strings.Join(list, ",")
	if _, ok := security.generateMiddle[key]; !ok {
		a := []common.AuthHandler{}
		for _, value := range list {
			a = append(a, security.middlewares[value])
		}
		security.generateMiddle[key] = common.AuthMiddle(a, security.fail)
	}
	return security.generateMiddle[key]
}

func (security *securityManager) Key(name string, location Location, middleware common.AuthHandler, def bool) string {
	security.schemaMap[name] = &swaggerSecurityScheme{
		Type: "apiKey",
		Name: name,
		In:   location,
	}
	security.middlewares[name] = middleware
	if def {
		security.d = append(security.d, name)
	}
	return name
}

func (security *securityManager) OnFail(f func() error) {
	security.fail = f
}

type proxyRouter struct {
	web.Router
	config *SwaggerConfig
}

type SwaggerRouterConfig struct {
	Url     string
	Tags    []SwaggerTag
	Name    string
	Info    SwaggerInfo
	Produce Produce
	Consume Consume
	Force   bool
}

func NewSwaggerRouter(path string, builder composer.Builder, router web.Router, config *SwaggerRouterConfig) *SwaggerRouter {
	if config.Url == "" {
		config.Url = "swagger"
	}
	if config.Produce == "" {
		config.Produce = JsonProduce
	}
	if config.Consume == "" {
		config.Consume = JsonConsume
	}
	if config.Name == "" {
		config.Name = config.Info.Title
	}

	swagger := &SwaggerRouter{Router: router, manager: &swaggerManager{}}
	manager := swagger.manager
	swagger.path = path

	manager.debug = builder.IsDebug()
	manager.config = config
	manager.Security = &securityManager{}
	manager.Security.init()
	manager.logger = builder.LoggerWrap("Swagger", "router")

	for _, tag := range config.Tags {
		manager.tags[tag.Name] = tag
	}
	manager.definitionRandom = 0
	manager.definitions = make(map[string]*swaggerSchema)
	manager.refDefinitions = make(map[string]interface{})

	proxy, ok := router.(*proxyRouter)
	if ok {
		if config.Info.Contact.Name == "" {
			config.Info.Contact = proxy.config.Contact
		}
		proxy.config.urls = append(proxy.config.urls, urlInfo{Url: path + manager.config.Url, Name: manager.config.Name})
	}
	return swagger
}

type SwaggerConfig struct {
	DomId        string
	ValidatorUrl string
	Url          string
	Contact      SwaggerContact
	Force        bool
	urls         []urlInfo
	logger       def.Logger
}
type swaggerResult struct {
	DomId        string    `json:"dom_id" yaml:"dom_id"`
	ValidatorUrl string    `json:"validatorUrl" yaml:"validatorUrl"`
	Urls         []urlInfo `json:"urls" yaml:"urls"`
}
type urlInfo struct {
	Url  string `json:"url" yaml:"url"`
	Name string `json:"name" yaml:"name"`
}

func BuildSwagger(builder composer.Builder, router web.Router, handler web.RouterHandler, config *SwaggerConfig) web.RouterHandler {
	if config.DomId == "" {
		config.DomId = "#swagger-ui"
	}
	if config.ValidatorUrl == "" {
		config.ValidatorUrl = "https://online.swagger.io/validator"
	}
	if config.Url == "" {
		config.Url = "swagger-config"
	}
	config.logger = builder.LoggerWrap("Swagger", "build")

	getInfo := func() *swaggerResult {
		result := &swaggerResult{}
		result.DomId = config.DomId
		result.ValidatorUrl = config.ValidatorUrl
		result.Urls = config.urls
		return result
	}

	if builder.IsDebug() || config.Force {
		router.Get("/"+config.Url+".json", func(context web.Context, next web.Next) error {
			return json.NewEncoder(context.Writer()).Encode(getInfo())
		})
		config.logger.Debugf("SwaggerConfig register:/%s.json", config.Url)
		router.Get("/"+config.Url+".yaml", func(context web.Context, next web.Next) error {
			return yaml.NewEncoder(context.Writer()).Encode(getInfo())
		})
		config.logger.Debugf("SwaggerConfig register:/%s.yaml", config.Url)
	}
	return func(path string) web.Router {
		r := &proxyRouter{Router: handler(path), config: config}
		return r
	}
}
func aliasWithParent(alias string, parentAlias string) string {
	return strings.Title(parentAlias) + strings.Title(alias)
}

var (
	queryReg = regexp.MustCompile(`\?.*`)
)

func pathToAlias(path string) string {
	a := []string{}
	for _, v := range strings.Split(queryReg.ReplaceAllString(path, ""), "/") {
		if strings.Index(v, "{") == -1 {
			a = append(a, strings.Title(strings.ToLower(v)))
		}
	}
	return strings.Join(a, "")
}

func formatPath(path string) string {
	return path
}

func Response(result interface{}, t Type) *SwaggerContent {
	if t == "" {
		t = Object
	}
	return &SwaggerContent{
		Schema: map[string]SwaggerSchema{
			"status": {
				Type:        Int,
				Required:    true,
				Description: "状态",
			},
			"result": {
				Type:     t,
				Required: true,
				Schema:   result,
			},
		},
	}
}
func PageResponse(result interface{}) *SwaggerContent {
	return &SwaggerContent{
		Schema: map[string]SwaggerSchema{
			"status": {
				Type:        Int,
				Required:    true,
				Description: "状态",
			},
			"result": {
				Type:     Object,
				Required: true,
				Object: map[string]SwaggerSchema{
					"total": {
						Type:     Int,
						Required: true,
					},
					"list": {
						Type:   Array,
						Schema: result,
					},
				},
			},
		},
	}
}

var (
	ExceptionResponse = &SwaggerContent{
		Schema: map[string]SwaggerSchema{
			"status": {
				Type:        Int,
				Required:    true,
				Description: "状态",
			},
			"message": {
				Type:     String,
				Required: true,
			},
		},
	}
	IdResponse = &SwaggerContent{
		Schema: map[string]SwaggerSchema{
			"status": {
				Type:        Int,
				Required:    true,
				Description: "状态",
			},
			"result": {
				Type:     Object,
				Required: true,
				Object: map[string]SwaggerSchema{
					"id": {
						Type:     Int,
						Required: true,
					},
				},
			},
		},
		Alias: "IdResponse",
	}
	ApiResponse = &SwaggerContent{
		Schema: map[string]SwaggerSchema{
			"status": {
				Type:        Int,
				Required:    true,
				Description: "状态",
			},
		},
		Alias: "ApiResponse",
	}
)
